/*
 * Copyright 2025 arisgo@163.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.arisgo.cloud.attendance.clazz.core.arrange;

import com.arisgo.cloud.attendance.clazz.core.ArrangeContext;
import com.arisgo.cloud.attendance.clazz.core.arrange.strategy.FullMatch;
import com.arisgo.cloud.attendance.clazz.entity.ClassDetail;
import com.arisgo.cloud.attendance.clazz.entity.ClassInfo;
import com.arisgo.cloud.attendance.clazz.mapper.ClassDetailMapper;
import com.arisgo.cloud.attendance.clazz.mapper.ClassInfoMapper;
import com.arisgo.cloud.attendance.clazz.mapper.StaffClassMapper;
import com.arisgo.cloud.attendance.clazz.vo.ClassInfoVo;
import com.arisgo.cloud.attendance.clazz.vo.TemporaryClassVo;
import com.arisgo.cloud.common.utils.AssertUtil;
import com.google.common.collect.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.List;

/**
 * 临时排班
 *
 * @author Coulson
 * @since 2025/3/26
 */
@Component
public class TemporaryArrange extends ArrangeAbstract {

    public static final String KEY = "temporary";
    private final ClassDetailMapper classDetailMapper;
    private final ClassInfoMapper classInfoMapper;
    private final StaffClassMapper staffClassMapper;

    public TemporaryArrange(MatchStore matchStore, ArrangeStore arrangeStore, ClassInfoMapper classInfoMapper,
                            StaffClassMapper staffClassMapper, ClassDetailMapper classDetailMapper) {
        super(matchStore, arrangeStore);
        this.classDetailMapper = classDetailMapper;
        this.classInfoMapper = classInfoMapper;
        this.staffClassMapper = staffClassMapper;
    }

    @Override
    public void validate(ArrangeContext context) {
        AssertUtil.notNull(context, "参数为空！");
        AssertUtil.notEmpty(context.getStaffIds(), "员工为空！");
        AssertUtil.notEmpty(context.getWorkdays(), "时间为空！");

        TemporaryClassVo temporaryClass = context.getTemporaryClass();
        AssertUtil.notNull(temporaryClass, "临时班为空！");
        AssertUtil.notNull(temporaryClass.getName(), "名称为空！");
        AssertUtil.notNull(temporaryClass.getStartTime(), "开始时间为空！");
        AssertUtil.notNull(temporaryClass.getEndTime(), "结束时间为空！");
    }

    /**
     * 临时排班
     */
    @Override
    public boolean arrange(ArrangeContext context) {
        long start = System.currentTimeMillis();
        logger.info("排班 => 开始: {}", start);
        // 验证参数
        this.validate(context);

        // 重置班次信息
        List<ClassInfoVo> classInfos = resetClassInfo(context);

        // 关联员工等其他信息
        String key = StringUtils.hasLength(context.getStrategy()) ? context.getStrategy() : FullMatch.KEY;
        matchStrategy(key).match(classInfos, context.getStaffIds());

        long end = System.currentTimeMillis();
        logger.info("排班 => 完成时间: {}，耗时: {}", end, end - start);
        return true;
    }

    protected List<ClassInfoVo> resetClassInfo(ArrangeContext context) {
        logger.info("临时排班 => 重置临时班");
        // 删除历史班
        this.delete(context);

        logger.info("临时排班 => 生成临时班");
        TemporaryClassVo temporaryClass = context.getTemporaryClass();
        List<LocalDate> workdays = context.getWorkdays();
        List<ClassInfo> classInfos = Lists.newArrayList();
        for (LocalDate workday : workdays) {
            ClassInfo classInfo = new ClassInfo();
            classInfo.setTenantId(context.getTenantId());
            classInfo.setGroupId(null);
            classInfo.setYear(workday.getYear());
            classInfo.setMonth(workday.getMonthValue());
            classInfo.setDay(workday.getDayOfMonth());
            classInfo.setWorkDate(workday);

            classInfo.setIsNormal(false);
            classInfo.setType(0);
            classInfo.setName(temporaryClass.getName());
            classInfo.setShortName(temporaryClass.getName());
            classInfo.setColor(temporaryClass.getColor());
            classInfo.setDuration(temporaryClass.getDuration());
            classInfo.setRemark(temporaryClass.getRemark());
            classInfos.add(classInfo);
        }
        classInfoMapper.insertBatch(classInfos);

        logger.info("临时排班 => 保存排班时间");
        ClassDetail detail = getClassDetail(context);
        List<ClassDetail> classDetails = Lists.newArrayList();
        List<ClassInfoVo> infos = Lists.newArrayList();
        for (ClassInfo classInfo : classInfos) {
            ClassDetail classDetail = new ClassDetail();
            BeanUtils.copyProperties(detail, classDetail);
            classDetail.setClassId(classInfo.getId());
            classDetails.add(classDetail);

            ClassInfoVo vo = new ClassInfoVo();
            BeanUtils.copyProperties(classInfo, vo);
            infos.add(vo);
        }
        classDetailMapper.insertBatch(classDetails);

        context.add(CLASS_INFO, classInfos);
        return infos;
    }

    private static ClassDetail getClassDetail(ArrangeContext context) {
        TemporaryClassVo temporaryClass = context.getTemporaryClass();
        String[] startTime = temporaryClass.getStartTime().split(":");
        String[] endTime = temporaryClass.getEndTime().split(":");

        ClassDetail detail = new ClassDetail();
        detail.setTenantId(context.getTenantId());
        detail.setStartTime(LocalTime.of(Integer.parseInt(startTime[0]), Integer.parseInt(startTime[1])));
        detail.setEndTime(LocalTime.of(Integer.parseInt(endTime[0]), Integer.parseInt(endTime[1])));
        detail.setDuration(temporaryClass.getDuration());

        if (temporaryClass.getRestStartTime() != null && temporaryClass.getRestEndTime() != null) {
            String[] restStartTime = temporaryClass.getRestStartTime().split(":");
            String[] restEndTime = temporaryClass.getRestEndTime().split(":");
            detail.setRestStartTime(LocalTime.of(Integer.parseInt(restStartTime[0]), Integer.parseInt(restStartTime[1])));
            detail.setRestEndTime(LocalTime.of(Integer.parseInt(restEndTime[0]), Integer.parseInt(restEndTime[1])));
        }
        return detail;
    }

    @Override
    public boolean delete(ArrangeContext context) {
        if (context.getTemporaryClass().getId() == null) {
            return true;
        }
        logger.info("临时排班 => 清空未到时间的临时班");
        Long classId = context.getTemporaryClass().getId();
        // 删除员工
        staffClassMapper.removeByClassId(context.getTenantId(), classId);
        // 删除班详情
        classDetailMapper.removeByClassId(context.getTenantId(), classId);
        // 删除班次
        classInfoMapper.deleteById(classId);
        return true;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        arrangeStore.add(KEY, this);
    }
}
